// 封装通用的模块
// 本地服务器 安装browser-sync yarn add browser-sync --dev
// 安装gulp yarn add gulp --dev
// 安装 gulp-load-plugins、gulp-sass(处理Ssass)
// 安装del  yarn add del --dev  清理编译的文件夹
// 安装 @babel/core @babel/preset-env 编译JS
const broserSync = require('browser-sync')
const bs = broserSync.create() // 创建一个服务器
const { src, dest, watch, parallel, series } = require('gulp')
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins() // 新建一个插件
const cwd = process.cwd() // 当前命令行所在的工作目录
let config = {
  build: {
    source: 'src', // 源文件夹
    dist: 'release', // 最终编译后存放的文件夹
    temp: '.temp', // 作为中间文件夹
    public: 'public', // 纯静态文件夹,
    paths: {
        styles: 'assets/styles/*.scss',
        scripts: 'assets/scripts/*.js',
        pages: '*.html',
        images: 'assets/images/**',
        fonts: 'assets/fonts/**'
    }
  }
}
try {
  const loadConfig = require(`${cmd}/pages.cconfig.js`)
  config = Object.assign({}, config, loadConfig)
} catch (e) {}
const del = require('del')
// 结构配置文件
const { build: configBuild, data } = config
const { source, dist, temp, public, paths: { styles, scripts, pages, images, fonts } } = configBuild
// 获取读取流的公共部分
const getBase = (src) => {
    return { base: src, cmd: src }
}
// 创建编译styles下的scss的任务
const style = () => {
    return src(`${source}/${styles}`, getBase(source)) //读取文件流
    .pipe(plugins.sass({ outputStyle: 'expanded' })) // 压缩CSS
    .pipe(dest(temp)) // 写入流中， 写入到temp(半成品)目录下
    .pipe(bs.reload({ stream: true })) // 写入流变化， 重新加载资源
}
// 创建编译scripts下的js的任务
// babel编译使用babel的下一代ES 编译
const script = () => {
    return src(`${source}/${scripts}`, getBase(source))
    .pipe(plugins.babel({ presets: [ require('@babel/preset-env') ] }))
    .pipe(dest(temp)) // 写入到temp(半成品)目录下
    .pipe(bs.reload({ stream: true }))
}
// gulp-swig 编译EJS yarn add gulp-swig --dev
const page = () => {
    return src(`${source}/${pages}`, getBase(source))
    .pipe(plugins.swig({ // 编译EJS
        data, // 传参
        defaults: {
            cache: false
        }
    }))
    .pipe(dest(temp))
    .pipe(bs.reload({ stream: true }))
}

const image = () => {
  return src(`${source}/${images}`, getBase(source))
  .pipe(plugins.imagemin()) // 图片压缩
  .pipe(dest(dist)) // 只有最终生产编译时, 直接保存到dist， 开发阶段不需要编译
}
const font = () => {
  return src(`${source}/${fonts}`, getBase(source))
  .pipe(plugins.imagemin())
  .pipe(dest(dist)) // 只有最终生产编译时, 直接保存到dist， 开发阶段不需要编译
}
const extra = () => { // 拷贝所有文件
  return src('**', { base: public, cmd: public})
  .pipe(dest(dist))
}
// 开发服务器任务
const serve = () => {
  // watch(`${source}/${styles}`, { cmd: src }, style) // 监听styles目录下文件改变， 改变就执行style任务
  // watch(`${source}/${scripts}`, { cmd: src }, script) // 监听scripts目录下文件改变， 改变就执行style任务
  // watch(`${source}/${pages}`, { cmd: src }, page) // 监听pages目录下文件改变， 改变就执行style任务
  // watch([`${source}/${images}`, `${source}/${fonts}`], { cmd: src }, bs.reload) // 监听， 重新加载
  // watch('**', { cmd: public }, bs.reload)
  bs.init({
    notify: false,
    port: 2080, // 端口
    open: false, // 启动服务器就打开浏览器
    server: {
      baseDir: [ temp, source, public ], // 依次按照目录顺序查找文件
      routes: {
        '/node_modules': 'node_modules'
      }
    }
  })
}
// gulp-useref这是一款可以将HTML引用的多个CSS和JS合并起来，减小依赖的文件个数，从而减少浏览器发起的请求次数
const useref = () => {
  return src(`${source}/${pages}`, getBase(source))
  .pipe(plugins.useref({ searchPath: [ temp, '.' ] })) // 从temp，.查找资源
  // HTML, JS, CSS 
  .pipe(plugins.if(/\.js$/, plugins.uglify()) // JS 代码压缩
  .pipe(plugins.if(/\.css$/, plugins.cleanCss())) // CSS 代码压缩
  .pipe(plugins.if(/\.html$/, plugins.htmlmin({ // html 代码压缩
    collapseWhitespace: true, // html展开空格
    minifyCSS: true,
    minifyJS: true
  })))
  .pipe(dest(dist)))
}
// 创建清理任务
const clean = () => {
  return del([dist, temp])
}
 // 编译任务 parallel 是并行执行顺序
 const compile = parallel(style, script, page)
 // 开发时执行的任务
 const develop = series(compile, serve)
 // 上线之前执行的任务
 const build = series(
   clean, // 清理文件夹
   image,
   font,
   extra,
   series(compile, useref) // 先编译好文件， 才能合并对应的资源
  )

module.exports = {
  develop,
    clean,
    build
}
